package com.winhxd.b2c.order.service.impl;

import com.winhxd.b2c.common.cache.Cache;
import com.winhxd.b2c.common.cache.Lock;
import com.winhxd.b2c.common.cache.RedisLock;
import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.constant.CacheName;
import com.winhxd.b2c.common.constant.OrderNotifyMsg;
import com.winhxd.b2c.common.constant.OrderSMSConstant;
import com.winhxd.b2c.common.context.CustomerUser;
import com.winhxd.b2c.common.domain.ResponseResult;
import com.winhxd.b2c.common.domain.customer.model.CustomerShoppingMallRule;
import com.winhxd.b2c.common.domain.message.condition.SMSCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderPayCallBackCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderPayInfoCondition;
import com.winhxd.b2c.common.domain.order.enums.OrderOperationPropertyEnum;
import com.winhxd.b2c.common.domain.order.enums.OrderPayMentPayStatusEnums;
import com.winhxd.b2c.common.domain.order.enums.OrderStatusEnum;
import com.winhxd.b2c.common.domain.order.enums.PayStatusEnum;
import com.winhxd.b2c.common.domain.order.model.OrderInfo;
import com.winhxd.b2c.common.domain.order.model.OrderLog;
import com.winhxd.b2c.common.domain.order.model.OrderPayment;
import com.winhxd.b2c.common.domain.order.vo.OrderDetailVO;
import com.winhxd.b2c.common.domain.order.vo.OrderPayVO;
import com.winhxd.b2c.common.domain.pay.condition.PayPreOrderCondition;
import com.winhxd.b2c.common.domain.pay.vo.PayPreOrderVO;
import com.winhxd.b2c.common.exception.BusinessException;
import com.winhxd.b2c.common.feign.pay.PayServiceClient;
import com.winhxd.b2c.common.util.DateUtil;
import com.winhxd.b2c.common.util.IpUtil;
import com.winhxd.b2c.common.util.JsonUtil;
import com.winhxd.b2c.common.util.MessageSendUtils;
import com.winhxd.b2c.order.dao.OrderDetailMapper;
import com.winhxd.b2c.order.dao.OrderInfoMapper;
import com.winhxd.b2c.order.dao.OrderLogMapper;
import com.winhxd.b2c.order.dao.OrderPaymentMapper;
import com.winhxd.b2c.order.service.OrderPayService;
import com.winhxd.b2c.order.service.OrderService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @description: 订单支付serviceImpl
 * @author: liuhanning
 * @create: 2019-01-08 11:29
 **/
@Service
public class OrderPayServiceImpl implements OrderPayService {

    private static final Logger logger = LoggerFactory.getLogger(OrderPayServiceImpl.class);
    private static final String DEFAULT_IP = "127.0.0.1";

    @Autowired
    private PayServiceClient payServiceClient;

    @Autowired
    private Cache cache;

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private OrderPaymentMapper orderPaymentMapper;

    @Autowired
    OrderLogMapper orderLogMapper;

    @Autowired
    MessageSendUtils messageSendUtils;


    @Transactional
    @Override
    public OrderPayVO getOrderPayInfo(OrderPayInfoCondition condition, CustomerUser customerUser) {


        String orderNo=condition.getOrderNo();
        String logTitle="订单支付serviceImpl--订单号："+orderNo;
        logger.info(logTitle+"开始");
        String spbillCreateIp=condition.getSpbillCreateIp();

        String deviceInfo=condition.getDeviceInfo();

        if (StringUtils.isBlank(orderNo)) {
            logger.info(logTitle+"为空");
            throw new BusinessException(BusinessCode.ORDER_NO_EMPTY);
        }

        if (StringUtils.isBlank(spbillCreateIp)) {
            spbillCreateIp = StringUtils.isNotBlank(IpUtil.getIpAddr()) ? IpUtil.getIpAddr() : DEFAULT_IP;
        }
        if (customerUser == null || customerUser.getCustomerId() == null || StringUtils.isBlank(customerUser.getOpenid())) {
            logger.info(logTitle+"登录凭证无效");
            throw new BusinessException(BusinessCode.CODE_1002);
        }
        Long customerId=customerUser.getCustomerId();
        String openid=customerUser.getOpenid();
        //订单信息
        OrderInfo orderInfo =orderInfoMapper.selectByOrderNo(orderNo);

        if (orderInfo == null || orderInfo.getCustomerId().longValue() != customerId.longValue()) {
            logger.info(logTitle+"订单信息有误");
            throw new BusinessException(BusinessCode.WRONG_ORDERNO);
        }
        if (OrderStatusEnum.WAIT_PAY.getStatusCode() != orderInfo.getStatus()) {
            logger.info(logTitle+"订单状态有误");
            throw new BusinessException(BusinessCode.WRONG_ORDER_STATUS);
        }
        int payType=orderInfo.getPayType();
        if (payType==0) {
            logger.info(logTitle+"支付方式为空");
            throw new BusinessException(BusinessCode.CODE_600106);
        }
        BigDecimal otherTotal=orderInfo.getOtherTotal();
        if (otherTotal==null||otherTotal.compareTo(BigDecimal.valueOf(0))<1) {
            logger.info(logTitle+"支付金额有误");
            throw new BusinessException(BusinessCode.CODE_600107);
        }
        //获取订单商品信息
        List<OrderDetailVO> orderDetailVOList=orderDetailMapper.selectListByOrderNo(orderNo);
        if (CollectionUtils.isEmpty(orderDetailVOList)){
            logger.info(logTitle+"未获取到订单商品信息");
            throw new BusinessException(BusinessCode.CODE_600108);
        }
        int spuNum=0;
        for (OrderDetailVO vo:orderDetailVOList) {
            spuNum+=vo.getNumber();
        }
        OrderPayVO ret=new OrderPayVO();
        String lockKey = CacheName.ORDER_PAY + orderNo;
        Lock lock = new RedisLock(cache, lockKey, 5000);
        if (lock.tryLock()) {
            logger.info("订单：{},customerId={},openid={};发起支付，获取支付信息开始", orderNo, customerId.toString(), openid);
            try {
                //支付 显示title
                String body = MessageFormat.format(OrderNotifyMsg.ORDER_ITEM_TITLE_4_PAYMENT, orderDetailVOList.get(0).getSpuName(),spuNum);
                PayPreOrderCondition payPreOrderCondition = new PayPreOrderCondition();
                payPreOrderCondition.setBody(body);
                payPreOrderCondition.setOutOrderNo(orderNo);
                payPreOrderCondition.setDeviceInfo(deviceInfo);
                payPreOrderCondition.setOpenid(openid);
                payPreOrderCondition.setPayType((short)payType);
                payPreOrderCondition.setSpbillCreateIp(spbillCreateIp);
                payPreOrderCondition.setTotalAmount(otherTotal);
//                payPreOrderCondition.setLimitPay(PAYMENT_NO_CREDIT);
                ResponseResult<PayPreOrderVO> responseResult = payServiceClient.prePay(payPreOrderCondition);
                if (responseResult == null || responseResult.getCode() != BusinessCode.CODE_OK || responseResult.getData() == null) {
                    logger.info(logTitle+"调用微信支付失败");
                    throw new BusinessException(BusinessCode.ORDER_GET_PAY_INFO_ERROR);
                }
                PayPreOrderVO payPreOrderVO = responseResult.getData();
                if (payPreOrderVO!=null) {

                    String timeStamp=payPreOrderVO.getTimeStamp();
                    String nonceStr=payPreOrderVO.getNonceStr();
                    String packageData=payPreOrderVO.getPackageData();
                    String signType=payPreOrderVO.getSignType();
                    String paySign=payPreOrderVO.getPaySign();
                    String orderTransactionNo=payPreOrderVO.getOutTradeNo();
                    String appid=payPreOrderVO.getAppId();
                    //插入流水数据
                    OrderPayment orderPayment=orderPaymentMapper.selectByOrderTransactionNo(orderTransactionNo);
                    if (orderPayment == null) {
                        orderPayment=new OrderPayment();
                        orderPayment.setOrderNo(orderNo);
                        orderPayment.setOrderTransactionNo(orderTransactionNo);
                        orderPayment.setCreated(new Date());
                        orderPayment.setBuyerId(openid);
                        orderPayment.setPayType(payType);
                        orderPayment.setRealPaymentMoney(otherTotal);
                        orderPayment.setCallbackStatus(OrderPayMentPayStatusEnums.PAYING.getCode());
                        orderPayment.setAppid(appid);
                        orderPaymentMapper.insertSelective(orderPayment);
                    }

                    ret.setNonceStr(nonceStr);
                    ret.setPackageData(packageData);
                    ret.setPaySign(paySign);
                    ret.setSignType(signType);
                    ret.setTimeStamp(timeStamp);
                    ret.setAppid(appid);
                }
            }finally {
                lock.unlock();
            }
        }else {
            logger.info(logTitle+"发起支付，出现并发，本次忽略");
            ret = null;
        }
        logger.info(logTitle+"结束");
        return ret;
    }
    @Override
    public Boolean orderPayCallBack(OrderPayCallBackCondition condition) {
        String log="支付回调orderPayCallBack--";
        if (condition==null) {
            logger.info(log+"--参数为空");
            return false;
        }
        logger.info(log+"参数："+condition);
        if (StringUtils.isBlank(condition.getOutOrderNo())) {
            logger.info(log+"--订单号为空");
            return false;
        }
        String orderNo=condition.getOutOrderNo();
        log+="--订单号--"+orderNo;

        logger.info(log+"--开始");
        // 更新流水号
        OrderPayment orderPayment=new OrderPayment();
        orderPayment.setOrderTransactionNo(condition.getOutTradeNo());
        orderPayment.setCallbackDate(new Date());
        orderPayment.setUpdated(new Date());
        orderPayment.setTimeEnd(condition.getTimeEnd());
        orderPayment.setCallbackStatus((int)condition.getStatus());
        orderPayment.setCallbackErrorCode(condition.getErrorCode());
        orderPayment.setCallbackErrorReason(condition.getErrorMessage());
        orderPayment.setTransactionId(condition.getTransactionId());
        orderPayment.setCallbackMoney(condition.getCallbackTotalAmount());
        orderPayment.setAppid(condition.getAppid());
        orderPayment.setAttach(condition.getAttach());
        orderPayment.setBody(condition.getBody());
        orderPayment.setDetail(condition.getDetail());
        orderPayment.setDeviceInfo(condition.getDeviceInfo());
        orderPayment.setMchId(condition.getMchId());
        orderPayment.setNonceStr(condition.getNonceStr());
        orderPayment.setTimeStart(condition.getTimeStart());
        orderPayment.setTimeExpire(condition.getTimeExpire());
        int insertResult=orderPaymentMapper.updateByOrderTransactionNoSelective(orderPayment);
        if (insertResult<1) {
            //订单更新失败
            logger.info(log+"--订单支付流更新失败");
        }
        //判断支付之后更新订单信息
        try{

            if(OrderPayMentPayStatusEnums.PAY_SUCCESS.getCode().shortValue()==(condition.getStatus())){
                //支付成功处理订单信息
                OrderInfo orderInfo=orderInfoMapper.selectByOrderNo(orderNo);
                if (orderInfo==null){
                    logger.info(log+"--未获取到订单信息");
                    return  false;
                }
                //判断订单状态
                if (PayStatusEnum.PAID.getStatusCode().equals(orderInfo.getPayStatus())){
                    //订单已支付
                    logger.info(log+"--订单已经支付，请勿重复支付");
                    return  true;
                }
                orderInfo.setPayTime(condition.getTimeEnd());
                orderInfo.setPayStatus(PayStatusEnum.PAID.getStatusCode());
                orderInfo.setStatus(OrderStatusEnum.WAIT_DELIVERING.getStatusCode());
                return  callBackUpdateOrder(orderInfo,log,OrderOperationPropertyEnum.PAY.getPropertyDes());
            }else if (OrderPayMentPayStatusEnums.PAY_FAIL.getCode().shortValue()==(condition.getStatus())){
                //支付失败 不做任何处理，订单保持“待付款”状态
                return  true;
            }
        }catch (Exception e){
            logger.error(log+"订单更新失败（异常）",e);
            return false;
        }
        return false;
    }


    private  boolean callBackUpdateOrder(OrderInfo orderInfo,String log,String operationProperty){
        String orderNo=orderInfo.getOrderNo();
        //更新订单信息
        orderInfo.setUpdated(new Date());
        int updateOrderResult=orderInfoMapper.updateByPrimaryKeySelective(orderInfo);
        if (updateOrderResult<1){
            logger.error(log+"订单更新失败");
            return  false;
        }
        //插入订单日志表
        OrderLog orderLog = new OrderLog();
        orderLog.setCreated(new Date());
        orderLog.setOrderNo(orderNo);
        orderLog.setOperationProperty(operationProperty);
        orderLogMapper.insertSelective(orderLog);
        try{
            orderMessageSend(orderInfo);
        }catch (Exception e){
            logger.info("创建订单发送短信---：异常");
        }
        return  true;
    }
    /**
     * 发送短信消息
     * @param orderInfo
     * @param
     */
    public void orderMessageSend(OrderInfo orderInfo){
        //订单短信通知TO运营
        CustomerShoppingMallRule customerShoppingMallRule = JsonUtil.parseJSONObject(cache.get(CacheName.SHOPPING_MALL_RULE), CustomerShoppingMallRule.class);
        if (customerShoppingMallRule==null || StringUtils.isBlank(customerShoppingMallRule.getOrderMobile())){
            logger.info("创建订单发送短信---：未获取到手机号");
            return;
        }
        if (orderInfo==null){
            logger.info("创建订单发送短信---：未获取到订单信息");
            return;
        }
        String orderMobile = customerShoppingMallRule.getOrderMobile();
        String contentData = DateUtil.dateToString(orderInfo.getCreated());
        String content = MessageFormat.format(OrderSMSConstant.createOrder_template,contentData, orderInfo.getOrderNo(),orderInfo.getOtherTotal());

        String[] mobile = orderMobile.split(",");
        for(String sendMobile : mobile){
            if (StringUtils.isBlank(sendMobile)){
                continue;
            }
            SMSCondition sMSCondition = new SMSCondition();
            sMSCondition.setContent(content);
            sMSCondition.setMobile(sendMobile);
            messageSendUtils.sendSms(sMSCondition);
            logger.info("创建订单发送短信---" +sendMobile + ":发送的内容为:" + content);
        }
    }

}
